/*
 * Copyright (C) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { HttpCache } from './http/HttpCache'
import { HttpRedirectHandler } from './http/callback/HttpRedirectHandler'
import { RequestCallBack } from './http/callback/RequestCallBack'
import { HttpRequest } from './http/client/HttpRequest'
import { HttpMethod } from './http/client/HttpMethod'
import { HttpHandler } from './http/HttpHandler'
import { RequestParams } from './http/RequestParams'
import { UploadConfig } from './http/UploadConfig';

export class HttpUtils {
    private httpRedirectHandler: HttpRedirectHandler;
    private responseTextCharset = "UTF-8";
    private currentRequestExpiry = HttpCache.prototype.getDefaultExpiryTime();
    private DEFAULT_RETRY_TIMES = 3;
    private HEADER_ACCEPT_ENCODING = "Accept-Encoding";
    private ENCODING_GZIP = "gzip";
    private DEFAULT_POOL_SIZE = 3;
    private connectTimeout = 60000; //连接超时时间
    private readTimeout = 60000; //读取超时时间
    private interceptorFunction: Function //拦截器回调函数

    // ***************************************** config *******************************************

    public setTextCharset(charSet: string): HttpUtils {
        this.responseTextCharset = charSet;
        return this;
    }

    public setHttpRedirectHandler(httpRedirectHandler: HttpRedirectHandler): HttpUtils {
        this.httpRedirectHandler = httpRedirectHandler;
        return this;
    }

    public setHttpCacheSize(httpCacheSize: number): HttpUtils {
        HttpCache.prototype.setCacheSize(httpCacheSize);
        return this;
    }

    public setDefaultHttpCacheExpiry(defaultExpiry: number): HttpUtils {
        HttpCache.prototype.setDefaultExpiryTime(defaultExpiry);
        this.currentRequestExpiry = HttpCache.prototype.getDefaultExpiryTime();
        return this;
    }

    public setCurrentHttpCacheExpiry(currRequestExpiry: number): HttpUtils {
        this.currentRequestExpiry = currRequestExpiry;
        return this;
    }

    public setTimeout(timeout: number): HttpUtils {
        this.connectTimeout = timeout
        return this;
    }

    public setSoTimeout(timeout: number): HttpUtils {
        this.readTimeout = timeout
        return this;
    }

    // ***************************************** upload *******************************************
    public upload(uploadConfig: UploadConfig, callback) {
        var handler = new HttpHandler(this.responseTextCharset, callback);
        handler.doInBackgroundUpload(uploadConfig)
    }

    public setInterceptor(interceptor?: Function) {
        this.interceptorFunction = interceptor
        return this
    }

    // ***************************************** send request *******************************************

    public send<T>(method: HttpMethod, url: string, callBack: RequestCallBack<T>): HttpHandler<T> {
        return this.sendParams(method, url, null, callBack);
    }

    public sendParams<T>(method: HttpMethod, url: string, params: RequestParams, callBack: RequestCallBack<T>): HttpHandler<T> {
        if (url == null) throw new Error('url may not be null')
        var request = new HttpRequest(method, url)

        return this.sendRequest(request, params, callBack);
    }

    // ***************************************** download *******************************************

    public download<T>(url: string, target: string,
                       callback: RequestCallBack<T>): HttpHandler<T> {
        return this.downloadReq(HttpMethod.GET, url, target, null, callback);
    }

    public downloadReq<T>(method: HttpMethod, url: string, target: string,
                          params: RequestParams, callback: RequestCallBack<T>): HttpHandler<T> {
        if (url == null) throw new Error("url may not be null");
        var request = new HttpRequest(method, url);
        var handler = new HttpHandler(this.responseTextCharset, callback);

        handler.setExpiry(this.currentRequestExpiry);
        handler.setHttpRedirectHandler(this.httpRedirectHandler);

        if (params != null) {
            request.setRequestParams(params);
            handler.setPriority(params.getPriority());
        }
        handler.executeOnExecutorDownload(request, target);
        return handler;
    }

    private sendRequest<T>(request: HttpRequest, params: RequestParams, callBack: RequestCallBack<T>): HttpHandler<T> {

        var handler = new HttpHandler(this.responseTextCharset, callBack);
        handler.setInterceptor(this.interceptorFunction)
        handler.setExpiry(this.currentRequestExpiry);
        handler.setHttpRedirectHandler(this.httpRedirectHandler);
        request.setRequestParams(params);

        if (params != null) {
            handler.setPriority(params.getPriority());
        }
        handler.executeOnExecutor(request);
        return handler;
    }
}
